//
// $Id: XChessFrame.java 8 2007-04-18 13:47:40Z z_hossain $
//
// xChess is a multiplatform graphical chess user interface
// Copyright (C) 2007  MD. Z. Hossain <z_hossain@users.sf.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
// 02110-1301, USA.
//
// For more information visit http://xchess.sourceforge.net
//

package gui;


import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;

import control.AbsAgent;
import control.AbsEngineAgent;
import event.EngineAdapter;
import event.EngineEvent;

import net.sourceforge.xchess.Utility;

public class XChessFrame extends JFrame implements IChessContext {
	
	private JMenuBar menuBar;
	private JScrollPane scrollOutputArea;
	private JScrollPane scrollMoveList;
	private JMenuItem hhItem;
	private JMenuItem hmItem;
	private JMenu newGameMenu;
	private ChessClock chessClock;
	private JPanel borderPanel;
	private JPanel sidePanel;
	private MoveListUI moveListUI;
	private BoardUI boardUI;
	private JTextArea outputArea;
	private JSplitPane horizontalSplit;
	private JSplitPane verticalSplit;
	private JMenuItem aboutItem;
	private JMenu helpMenu;
	private JMenuItem exitItem;
	private JMenu fileMenu;
	
	private AbsAgent alphaAgent;
	private AbsAgent betaAgent;
	
	public XChessFrame() {
		initGUI();
		newGame(AbsAgent.USER_AGENT, AbsAgent.USER_AGENT);
	}
	
	private void initGUI() {
		try {
			
			this.setTitle("xChess 0.03");
			this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
			this.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("logo16.png")).getImage());

			verticalSplit = new JSplitPane();
			getContentPane().add(verticalSplit, BorderLayout.CENTER);
			verticalSplit.setOrientation(JSplitPane.VERTICAL_SPLIT);
			verticalSplit.setDividerSize(5);
			verticalSplit.setDividerLocation(413);

			scrollOutputArea = new JScrollPane();
			verticalSplit.add(scrollOutputArea, JSplitPane.BOTTOM);

			outputArea = new JTextArea();
			scrollOutputArea.setViewportView(outputArea);
			outputArea.setEditable(false);

			horizontalSplit = new JSplitPane();
			verticalSplit.add(horizontalSplit, JSplitPane.LEFT);
			horizontalSplit.setDividerSize(6);
			horizontalSplit.setDividerLocation(411);
			
			sidePanel = new JPanel();
			sidePanel.setLayout(new BorderLayout());
			horizontalSplit.add(sidePanel, JSplitPane.RIGHT);
			
			scrollMoveList = new JScrollPane();
			sidePanel.add(scrollMoveList, BorderLayout.CENTER);

			chessClock = new ChessClock();
			sidePanel.add(chessClock, BorderLayout.NORTH);

			moveListUI = new MoveListUI();
			moveListUI.setFont(moveListUI.getFont().deriveFont(java.awt.Font.BOLD, 16));
			scrollMoveList.setViewportView(moveListUI);
			moveListUI.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

			borderPanel = new JPanel();
			borderPanel.setLayout(new BorderLayout());
			borderPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
			horizontalSplit.add(borderPanel, JSplitPane.LEFT);

			boardUI = new BoardUI();
			borderPanel.add(boardUI, BorderLayout.CENTER);

			menuBar = new JMenuBar();
			setJMenuBar(menuBar);

			fileMenu = new JMenu();
			menuBar.add(fileMenu);
			fileMenu.setText("File");

			newGameMenu = new JMenu();
			fileMenu.add(newGameMenu);
			newGameMenu.setText("New Game");

			hmItem = new JMenuItem();
			newGameMenu.add(hmItem);
			hmItem.setText("Human - Machine");
			hmItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					newGame(AbsAgent.USER_AGENT, AbsAgent.ENGINE_AGENT);
				}
			});

			hhItem = new JMenuItem();
			newGameMenu.add(hhItem);
			hhItem.setText("Human - Human");
			hhItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					newGame(AbsAgent.USER_AGENT, AbsAgent.USER_AGENT);
				}
			});

			helpMenu = new JMenu();
			menuBar.add(helpMenu);
			helpMenu.setText("Help");

			aboutItem = new JMenuItem();
			helpMenu.add(aboutItem);
			aboutItem.setText("About xChess");
			aboutItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					new AboutDialog(XChessFrame.this).setVisible(true);
				}
			});

			fileMenu.add(new JSeparator());

			exitItem = new JMenuItem();
			fileMenu.add(exitItem);
			exitItem.setText("Exit");

			exitItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					System.exit(0);
				}
			});

			this.setSize(575, 574);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void newGame(int agent1, int agent2) {
		if(alphaAgent != null) alphaAgent.dispose();
		if(betaAgent != null) betaAgent.dispose();
		outputArea.setText("");
		chessClock.stop();
		chessClock.setTime(600000);
		chessClock.setTurn(ChessClock.WHITE_TURN);
		boardUI.setBoard(Utility.INITIAL_BOARD);
		moveListUI.clear();
		
		alphaAgent = AbsAgent.createAgent(XChessFrame.this, agent1);
		betaAgent = AbsAgent.createAgent(XChessFrame.this, agent2);
		alphaAgent.setOpponentAgent(betaAgent);
		alphaAgent.setTurn(ChessClock.WHITE_TURN);
		betaAgent.setOpponentAgent(alphaAgent);
		betaAgent.setTurn(ChessClock.BLACK_TURN);
		alphaAgent.newGame();
		betaAgent.newGame();
		
		if(betaAgent instanceof AbsEngineAgent) {
			((AbsEngineAgent)betaAgent).addEngineListener(new EngineAdapter() {

				@Override
				public void dataPrinted(EngineEvent e) {
					outputArea.setText(outputArea.getText() + "[OUT] " + e.getData() + "\n");
				}
	
				@Override
				public void dataEntered(EngineEvent e) {
					outputArea.setText(outputArea.getText() + "[IN] " + e.getData() + "\n");
				}
			});
		}
	}
	
	public BoardUI getBoardUI() {
		return boardUI;
	}

	public ChessClock getChessClock() {
		return chessClock;
	}

	public MoveListUI getMoveListUI() {
		return moveListUI;
	}
}
